package org.flowersinthesand.room;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;

import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.transport.THttpClient;
import org.flowersinthesand.jquerysocket.Connection;
import org.flowersinthesand.jquerysocket.EventHandler;
import org.flowersinthesand.jquerysocket.On;

import biscuit.data.Document;
import biscuit.data.Room;
import biscuit.data.User;

import com.evernote.edam.error.EDAMErrorCode;
import com.evernote.edam.error.EDAMUserException;
import com.evernote.edam.notestore.NoteStore;
import com.evernote.edam.type.Note;
import com.evernote.edam.type.Notebook;
import com.evernote.edam.type.Publishing;

@EventHandler("/app")
public class AppHandler {

	private ServletContext servletContext;
	private Map<String, Connection> connections;
	private Connection connection;
	private Object data;

	@On("init")
	@SuppressWarnings("unchecked")
	public Room init() {
		List<Room> roomList = (List<Room>) servletContext.getAttribute("roomList");
		String parameter = (String) data;
		String id = parameter.substring(0, parameter.indexOf("?"));
		connection.data().put("userId", id);
		
		String search = parameter.substring(parameter.indexOf("?") + 1);
		if (search.indexOf("index") != 0) {
			Room room = new Room(decode(search.substring("title=".length())), new User(id));
			roomList.add(room);
			room.setIndex(roomList.size() - 1);
			connection.data().put("index", roomList.size() - 1);
		} else {
			connection.data().put("index", new Integer(search.substring("index=".length())));
			roomList.get((Integer) connection.data().get("index")).addUser(new User(id));
		}
		
		for (Connection conn : connections.values()) {
			if (connection != conn) {
				conn.send("entrance", id);
			}
		}
		
		return roomList.get((Integer) connection.data().get("index"));
	}
	
	private String decode(String string) {
		try {
			return URLDecoder.decode(string, "utf-8");
		} catch (UnsupportedEncodingException e) {
			return null;
		}
	}
	
	@On("note")
	@SuppressWarnings("unchecked")
	public void note() {
		for (Connection conn : connections.values()) {
			if (connection != conn) {
				conn.send("note", data);
			}
		}
		
		int index = (Integer) connection.data().get("index");
		
		Document document = new Document();
		document.setContent((String) data);
		((List<Room>) servletContext.getAttribute("roomList")).get(index).getDocuHistory().add(document);
	}
	
	@On("klose")
	public void klose() {
		String id = (String) connection.data().get("userId");
		
		for (Connection conn : connections.values()) {
			if (connection != conn) {
				conn.send("exit", id);
			}
		}
		
		int index = (Integer) connection.data().get("index");
		@SuppressWarnings("unchecked")
		List<Room> roomList = ((List<Room>) servletContext.getAttribute("roomList")); 
		Room room = roomList.get(index);
		
		List<User> userList = room.getUserList();
		for (int i = 0; i < userList.size(); i++) {
			if (userList.get(i).getId().equals(id)) {
				userList.remove(i);
				break;
			}
		}
		
		if (userList.size() == 0) {
			roomList.remove(index);
		}
	}

	@On("chat")
	public void chat() {
		for (Connection conn : connections.values()) {
			conn.send("chat", data);
		}
	}

	@On("exitroom")
	public void exitroom() {
		
		String noteStoreUrlBase = "https://www.evernote.com/edam/note/";
		
		@SuppressWarnings("unchecked")
		Map<String, Object> map = (Map<String, Object>) data;
		String accessToken = (String) map.get("accessToken");
		String shardId = (String) map.get("shardId");
		Boolean share = (Boolean) map.get("share");
		
		int index = (Integer) connection.data().get("index");

		try {
			if (accessToken != null) {
				
				// noteStore 를 얻어낸다.
				String noteStoreUrl = noteStoreUrlBase + shardId;
				THttpClient noteStoreTrans;
				noteStoreTrans = new THttpClient(noteStoreUrl);
				TBinaryProtocol noteStoreProt = new TBinaryProtocol(noteStoreTrans);
				NoteStore.Client noteStore = new NoteStore.Client(noteStoreProt, noteStoreProt);
		
				// 방 정보를 추출한다.
				@SuppressWarnings("unchecked")
				List<Room> roomList = (List<Room>) servletContext.getAttribute("roomList");
				
				int docuHistorySize = roomList.get(index).getDocuHistory().size();
				String lastDocu;

				if (docuHistorySize > 0) {
					lastDocu = roomList.get(index).getDocuHistory().get(docuHistorySize-1).getContent();
				} else {
					lastDocu = "";
				}
				
				String notebookName = "BISCUIT";
				String noteName = roomList.get(index).getTitle();
				String content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
						+ "<!DOCTYPE en-note SYSTEM \"http://xml.evernote.com/pub/enml2.dtd\">"
						+ "<en-note>"
						+ lastDocu
						+ "</en-note>";
				
				// 에버노트에 자료를 저장한다.
				createNotebook(noteStore, accessToken, notebookName, noteName, content);
				
				// 공유를 할 지 결정한다.
				if (share.equals(true)) {
					System.err.println("test");
					shareNotebook(noteStore, accessToken, notebookName);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private void createNotebook(NoteStore.Client noteStore, String accessToken, String notebookName, String noteName, String content) throws Exception {

		// 새로운 노트북을 만든다.
		Notebook newNotebook = new Notebook();
		newNotebook.setName(notebookName);

		// 만들거나 찾을 노트북 변수를 선언한다.
		Notebook createdNotebook = null;

		try {
			
			// 노트 이름이 겹치는 것이 없을 경우 그냥 생성한다.
			createdNotebook = noteStore.createNotebook(accessToken, newNotebook);

		} catch (EDAMUserException e) {
			
			if (e.getErrorCode() == EDAMErrorCode.DATA_CONFLICT) {
				
				// 노트 이름이 겹칠 경우 (DATA_CONFLICT) 이미 있는 노트북의 GUID 를 추출한다.

				// 모든 노트북을 리스트한다.
				List<Notebook> notebooks = noteStore.listNotebooks(accessToken);

				// 만들려고 했던 이름을 가지는 노트북을 찾는다.
				for (Notebook tempNotebook : notebooks) {
					
					if (tempNotebook.getName().equals(notebookName)) {
						
						createdNotebook = tempNotebook;
						
						// 노트북을 찾았으면 Escape
						break;
					}
				}

			} else {
				
				e.printStackTrace();
				
				return;
			}
		}
		
		// 대상 노트북으로부터 GUID 를 추출한다.
		String createdNotebookGuid = createdNotebook.getGuid();

	//	println(response, "Successfully created a new notebook with GUID: " + createdNotebookGuid);
		
		Note newNote = new Note();

		newNote.setTitle(noteName);
	//	newNote.setTitle("Note made in Notebook GUID(" + createdNotebookGuid + ")");
		newNote.setContent(content);
		
		newNote.setNotebookGuid(createdNotebookGuid);
		
		noteStore.createNote(accessToken, newNote);
		
	//	Note createdNote = noteStore.createNote(accessToken, newNote);
	//	String createdNoteGuid = createdNote.getGuid();

	//	println(response, "Successfully created a new note with GUID: " + createdNoteGuid);
	//	println(response, "Added to the notebook");
	//	println(response, "");
	}
	
	private void shareNotebook(NoteStore.Client noteStore, String accessToken, String notebookName) throws Exception {
	
		// 공유할 노트북을 찾는다.

		// 모든 노트북을 리스트한다.
		List<Notebook> notebooks = noteStore.listNotebooks(accessToken);

		// 주어진 이름을 가지는 노트북을 찾는다.
		for (Notebook tempNotebook : notebooks) {
			
			if (tempNotebook.getName().equals(notebookName)) {

				Publishing publishing = new Publishing();
				publishing.setUri(notebookName);

				tempNotebook.setPublishing(publishing);
				tempNotebook.setPublished(true);

				noteStore.updateNotebook(accessToken, tempNotebook);
				
				break;
			}
		}
	}
}
